package stream;

import java.util.*;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.partitioningBy;

/**
 * Created by Robo on 2017/9/23.
 */
public class StreamTest {
    public static void main(String[] args) {
        Set<Integer> sets = new HashSet<>();
        sets.add(992);
        sets.add(761);
        sets.add(6874);
        sets.add(3879);
        System.out.println(sets);

        filter();
        flatMap();
        collectValue();
        System.out.println(partitionPrimes(29));
//        System.out.println(JSON.toJSONString(partitionPrimes(29)));
        main2();
    }

    public static void flatMap() {
        List<String> words = Arrays.asList("Java8", "Lambdas", "In", "Action");
//        Predicate predicate =
        //flatmap执行前需要先toArray一下
        //xfList.stream().map(xf->xf.getGwkhkmx().toArray()).flatMap(Arrays::stream).collect(Collectors.toList());
        List<String> uniqueChar = words.stream().map(w -> w.split(""))
                .flatMap(Arrays::stream).distinct().collect(Collectors.toList());
        System.out.println("flatMap=="+uniqueChar);
    }
    public static void filter() {
        List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5,6);
        List<Integer> sum = nums.stream().filter(n -> n % 2 == 0).collect(Collectors.toList());
        //findFirst
        Integer first = nums.stream().filter(n -> n > 5).findFirst().get();
        System.out.println(first);
        System.out.println("filter"+sum);
    }
    public static void reduce() {
        List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
        int sum = nums.stream().reduce(0, (a, b) -> a + b);
        int sum2 = nums.stream().reduce(0,Integer::sum);

        System.out.println(sum);
    }

    public static void limitValue() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> max = numbers.stream().reduce(Integer::max);
        System.out.println(max);
    }

    public static void function() {
        Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
        Stream.generate(Math::random).limit(5).forEach(System.out::println);
//        Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);
    }

    public static void collectValue() {
        List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
        Map<Integer, List<Integer>> collect = numbers.stream().collect(groupingBy(i -> i % 2));
//        Map<Boolean, List<Integer>> collect = numbers.stream().collect(partitioningBy(i -> i % 2 ==0 ));
        System.out.println(collect);
    }

    //如果n不能被2到它的平方根之间的自然数整除，那么n也不能被大于它的平方根在自然数整除
    public static boolean isPrime(int n){
//        int root = (int) Math.sqrt((double) n);
//        return IntStream.range(2, root == 2 ? 3 : root).noneMatch(i -> n % i == 0);
        return IntStream.range(2, n < 5 ? n : (int) Math.sqrt((double) n)).noneMatch(i -> n % i == 0);
    }

//    将质数和非质数分区
    //{false=[4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28], true=[2, 3, 5, 7, 11, 13, 17, 19, 23]}
    //{false=[4, 10, 12, 14, 16, 18, 20, 21, 22, 24, 26, 27, 28], true=[2, 3, 5, 6, 7, 8, 9, 11, 13, 15, 17, 19, 23, 25]}

    public static Map<Boolean, List<Integer>> partitionPrimes(int n){
        return IntStream.range(2, n).boxed().collect(Collectors.partitioningBy(i -> isPrime(i)));
    }

    public static  void  main2(){
        //1.分组计数
        List<Student> list1= Arrays.asList(
                new Student(1,"one","zhao"),
                new Student(2,"one","qian"),
                new Student(3,"two","sun"));
        //1.1根据某个属性分组计数
        Map<String,Long> result1=list1.stream().collect(Collectors.groupingBy(Student::getName,Collectors.counting()));
        System.out.println(result1);
        //1.2根据整个实体对象分组计数,当其为String时常使用
        Map<Student,Long> result2=list1.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
        System.out.println(result2);
        //1.3根据分组的key值对结果进行排序、放进另一个map中并输出
        Map<String,Long> xMap=new HashMap<>();
        result1.entrySet().stream().sorted(Map.Entry.<String,Long>comparingByKey().reversed()) //reversed不生效
                .forEachOrdered(x->xMap.put(x.getKey(),x.getValue()));
        System.out.println(xMap);

        //2.分组，并统计其中一个属性值得sum或者avg:id总和
        Map<String,Integer> result3=list1.stream().collect(
                Collectors.groupingBy(Student::getName,Collectors.summingInt(Student::getGroupId))
        );
        System.out.println(result3);

        //{one=[zhao, qian], two=[sun]} value组装成list
        Map<String, List<String>> result4 = list1.stream().collect(
                groupingBy(Student::getClassName, Collectors.mapping(Student::getName, Collectors.toList()))
        );
        System.out.println(result4);

        //{one={qian=2, zhao=1}, two={sun=3}} value组装成map
        Map<String, ConcurrentMap<String,Integer>> result5 = list1.stream().collect(
                groupingBy(Student::getClassName, Collectors.toConcurrentMap(Student::getName, Student::getGroupId, (a, b) -> b))
        );
        System.out.println(result5);
    }
}
